use common_base::{async_trait::async_trait, prelude::*, sqlx::Connection};
use common_core::{
    data::{DataModel, MetadataType},
    ServiceContext, ServiceContextBase, ServiceContextBuilder,
};

use crate::{context::MDMContext, metadata::MetadataManager, model::MdmDataModel};

pub struct MdmLoadServiceContextBuilder;

impl Default for MdmLoadServiceContextBuilder {
    fn default() -> Self {
        Self {}
    }
}

#[async_trait]
impl ServiceContextBuilder for MdmLoadServiceContextBuilder {
    async fn new_context(&self, srv_ctx_base: ServiceContextBase) -> Box<dyn ServiceContext> {
        let context = MDMContext::get_instance(srv_ctx_base);
        // context.set_connection()
        // context.set_statment()
        // if ( DICTSaveDataUtils.isGetBackGeneratedCols(mdmContext) ) {
        //     mdmContext.getParamObject().setParam("roCols", new RoColsBean());
        // }
        Box::new(context)
    }

    async fn create_response(
        &self,
        srv_ctx: &mut dyn ServiceContext,
    ) -> Result<Option<Box<dyn DataModel>>> {
        let mut mdm_context = MDMContext::downcast_from_mut(srv_ctx)?;

        let biz_id = mdm_context.get_value_by_param_name("MDL_ID").to_owned();
        let dct_id = mdm_context.get_value_by_param_name("DCT_ID").to_owned();

        let biz_metadata = MetadataManager::get_instance(MetadataType::Biz)
            .get_metadata(mdm_context.get_service_context_base_mut(), biz_id.as_str())
            .await?;

        let mut dct_metadata = None;
        if let Some(biz_metadata) = &biz_metadata {
            dct_metadata = biz_metadata
                .as_biz_metadata()
                .unwrap()
                .get_dct_metadata(mdm_context.get_service_context_base(), dct_id.as_str())
                .and_then(|v| Some(v.clone()))
        }
        if dct_metadata.is_none() {
            dct_metadata = MetadataManager::get_instance(MetadataType::Dct)
                .get_metadata(mdm_context.get_service_context_base_mut(), dct_id.as_str())
                .await?
        } else {
            mdm_context.biz_metadata = biz_metadata;
        }
        // mdm_context.dct_metadata = dct_metadata;

        let mut mdm_model = MdmDataModel::default();
        mdm_model.mdl_id = biz_id;

        // Juts for test
        // if mdm_context
        //     .get_param_object()
        //     .get_value_by_param_name("isGetMetaData")
        //     .eq("1")
        if let Some(dct_metadata) = dct_metadata {
            mdm_model.set_value("metaData", dct_metadata);
        }

        // if mdm_context
        //     .get_param_object()
        //     .get_value("ws_err_map")
        //     .is_some()
        // {
        //     let param_obj = mdm_context.get_param_object();
        //     mdm_context
        //         .get_response_object()
        //         .set_addon_object(param_obj);
        // }

        Ok(Some(Box::new(mdm_model)))
    }

    async fn finish_context(&self, srv_ctx: &mut dyn ServiceContext) -> Result<()> {
        if let Some(conn) = srv_ctx.take_connection() {
            conn.close().await?
        }
        Ok(())
    }
}
